using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using LambdaBuilder.Resolver;

namespace Catastrophe.Common.AttributeEx
{
	public class BuildAttribute
	{
		public static ComDataAttribute GetComAb<T>(string propertyName)
		{
			PropertyInfo property = typeof(T).GetProperty(propertyName);
			if (property == null)
			{
				throw new Exception("目标属性不存在！");
			}
			return Attribute.GetCustomAttribute(property, typeof(ComDataAttribute)) as ComDataAttribute;
		}

		public static ComNcAttribute GetComNcAb<T>(string propertyName)
		{
			PropertyInfo property = typeof(T).GetProperty(propertyName);
			if (property == null)
			{
				throw new Exception("目标属性不存在！");
			}
			return Attribute.GetCustomAttribute(property, typeof(ComNcAttribute)) as ComNcAttribute;
		}

		public static TAb GetCustomAb<T, TAb>(string propertyName) where TAb : Attribute
		{
			PropertyInfo property = typeof(T).GetProperty(propertyName);
			if (property == null)
			{
				throw new Exception("目标属性不存在！");
			}
			return Attribute.GetCustomAttribute(property, typeof(TAb)) as TAb;
		}

		public static TAb GetCustomAb<T, TAb>(PropertyInfo propertyInfo) where TAb : Attribute
		{
			if (propertyInfo == null)
			{
				throw new ArgumentNullException("propertyInfo");
			}
			return Attribute.GetCustomAttribute(propertyInfo, typeof(TAb)) as TAb;
		}

		public static List<TAb> GetCustomAbList<T, TAb>(BindingFlags flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public) where T : class, new()where TAb : Attribute
		{
			Type typeFromHandle = typeof(T);
			List<PropertyInfo> list = new List<PropertyInfo>();
			list.AddRange(typeFromHandle.GetProperties(flags));
			List<TAb> list2 = new List<TAb>();
			foreach (PropertyInfo item in list)
			{
				TAb val = Attribute.GetCustomAttribute(item, typeof(TAb)) as TAb;
				if (val != null)
				{
					list2.Add(val);
				}
			}
			return list2;
		}

		public static List<TAb> GetEnumCustomAbList<T, TAb>() where TAb : Attribute
		{
			Type typeFromHandle = typeof(T);
			if (!typeFromHandle.IsEnum)
			{
				throw new Exception("目标类型不是Enum");
			}
			List<TAb> list = new List<TAb>();
			MemberInfo[] members = typeof(T).GetMembers(BindingFlags.Static | BindingFlags.Public);
			MemberInfo[] array = members;
			foreach (MemberInfo element in array)
			{
				TAb val = Attribute.GetCustomAttribute(element, typeof(TAb)) as TAb;
				if (val != null)
				{
					list.Add(val);
				}
			}
			return list;
		}

		public static TAb GetEnumCustomAb<T, TAb>(Enum value) where TAb : Attribute
		{
			return BuildAttribute.GetEnumCustomAb<T, TAb>(value?.ToString());
		}

		public static TAb GetEnumCustomAb<T, TAb>(string name) where TAb : Attribute
		{
			Type typeFromHandle = typeof(T);
			if (!typeFromHandle.IsEnum)
			{
				throw new Exception("目标类型不是Enum");
			}
			MemberInfo memberInfo = typeof(T).GetMember(name, BindingFlags.Static | BindingFlags.Public).FirstOrDefault();
			if (memberInfo == null)
			{
				return null;
			}
			TAb val = Attribute.GetCustomAttribute(memberInfo, typeof(TAb)) as TAb;
			if (val != null)
			{
				return val;
			}
			return null;
		}

		public static T? GetEnumValue<T>(string value) where T : struct
		{
			if (value == null)
			{
				return null;
			}
			Type typeFromHandle = typeof(T);
			Attribute customAttribute = Attribute.GetCustomAttribute(typeFromHandle, typeof(FlagsAttribute));
			if (customAttribute != null)
			{
				if (!value.Contains(','))
				{
					if (Enum.IsDefined(typeFromHandle, value))
					{
						return (T)Enum.Parse(typeFromHandle, value);
					}
				}
				else if (!value.Replace(" ", "").Split(',').ToList()
					.Except(Enum.GetNames(typeFromHandle).ToList())
					.Any())
				{
					return (T)Enum.Parse(typeFromHandle, value);
				}
			}
			else if (Enum.IsDefined(typeFromHandle, value))
			{
				return (T)Enum.Parse(typeFromHandle, value);
			}
			return null;
		}

		public static T? GetEnumValue<T>(int value) where T : struct
		{
			try
			{
				object obj = Enum.ToObject(typeof(T), value);
				return (T?)obj;
			}
			catch (Exception)
			{
				return null;
			}
		}

		public static List<DescribeInfoAttribute> GetDescribeList<T>(BindingFlags flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)
		{
			Type typeFromHandle = typeof(T);
			List<PropertyInfo> list = new List<PropertyInfo>();
			list.AddRange(typeFromHandle.GetProperties(flags));
			List<DescribeInfoAttribute> list2 = new List<DescribeInfoAttribute>();
			foreach (PropertyInfo item in list)
			{
				DescribeInfoAttribute describeInfoAttribute = Attribute.GetCustomAttribute(item, typeof(DescribeInfoAttribute)) as DescribeInfoAttribute;
				if (describeInfoAttribute != null)
				{
					describeInfoAttribute.Name = item.Name;
					list2.Add(describeInfoAttribute);
				}
			}
			return list2;
		}

		public static DescribeInfoAttribute GetPropertyDescribe(PropertyInfo property, BindingFlags flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)
		{
			return Attribute.GetCustomAttribute(property, typeof(DescribeInfoAttribute)) as DescribeInfoAttribute;
		}

		public static T? GetDescribeEnum<T>(string describe) where T : struct, Enum
		{
			if (describe == null)
			{
				throw new ArgumentNullException("describe");
			}
			IEnumerable<string> enumerable = describe.Split(',')?.Where((string x) => !string.IsNullOrWhiteSpace(x))?.Select((string x) => x.Trim());
			if (enumerable == null)
			{
				return null;
			}
			int num = 0;
			FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public);
			foreach (string item in enumerable)
			{
				FieldInfo fieldInfo = null;
				FieldInfo[] array = fields;
				foreach (FieldInfo fieldInfo2 in array)
				{
					DescribeInfoAttribute describeInfoAttribute = Attribute.GetCustomAttribute(fieldInfo2, typeof(DescribeInfoAttribute)) as DescribeInfoAttribute;
					if (describeInfoAttribute != null && describeInfoAttribute.Description == item)
					{
						fieldInfo = fieldInfo2;
						break;
					}
				}
				if (fieldInfo == null || !Enum.TryParse<T>(fieldInfo.Name, out var result))
				{
					continue;
				}
				int num2 = Convert.ToInt32(result);
				if (num2 <= 0)
				{
					if (enumerable.Count() == 1)
					{
						return result;
					}
					throw new Exception("参数有误");
				}
				num = ((num != 0) ? (num | num2) : num2);
			}
			return (T)Enum.ToObject(typeof(T), num);
		}

		public static List<DescribeInfoAttribute> GetEnumDescribe<T>()
		{
			Type typeFromHandle = typeof(T);
			if (!typeFromHandle.IsEnum)
			{
				throw new Exception("目标类型不是Enum");
			}
			List<DescribeInfoAttribute> list = new List<DescribeInfoAttribute>();
			FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public);
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				DescribeInfoAttribute describeInfoAttribute = Attribute.GetCustomAttribute(fieldInfo, typeof(DescribeInfoAttribute)) as DescribeInfoAttribute;
				if (describeInfoAttribute != null)
				{
					describeInfoAttribute.Name = fieldInfo.Name;
					describeInfoAttribute.Value = (int)fieldInfo.GetValue(null);
					list.Add(describeInfoAttribute);
				}
			}
			return list;
		}

		public static List<DescribeInfoAttribute> GetEnumDescribeMulti<T>(params T[] ary)
		{
			Type typeFromHandle = typeof(T);
			if (!typeFromHandle.IsEnum)
			{
				throw new Exception("目标类型不是Enum");
			}
			List<DescribeInfoAttribute> list = new List<DescribeInfoAttribute>();
			FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public);
			FieldInfo[] array = fields;
			foreach (FieldInfo each in array)
			{
				if (!ary.All((T x) => x.ToString() != each.Name))
				{
					DescribeInfoAttribute describeInfoAttribute = Attribute.GetCustomAttribute(each, typeof(DescribeInfoAttribute)) as DescribeInfoAttribute;
					if (describeInfoAttribute != null)
					{
						describeInfoAttribute.Name = each.Name;
						describeInfoAttribute.Value = (int)each.GetValue(null);
						list.Add(describeInfoAttribute);
					}
				}
			}
			return list;
		}

		public static List<MemberInfo> GetEnumAllMembers<T>()
		{
			return typeof(T).GetMembers(BindingFlags.Static | BindingFlags.Public).ToList();
		}

		public static List<string> GetEnumMembers<T>()
		{
			Type typeFromHandle = typeof(T);
			if (!typeFromHandle.IsEnum)
			{
				throw new Exception("目标类型不是Enum");
			}
			List<string> list = new List<string>();
			FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public);
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				list.Add(fieldInfo.Name);
			}
			return list;
		}

		public static DescribeInfoAttribute GetEnumDescribe<T>(int enumValue) where T : struct
		{
			Type typeFromHandle = typeof(T);
			if (!typeFromHandle.IsEnum)
			{
				throw new Exception("目标类型不是Enum");
			}
			string text = Enum.ToObject(typeof(T), enumValue)?.ToString();
			if (text == null)
			{
				return null;
			}
			return BuildAttribute.GetEnumDescribe<T>(text);
		}

		public static DescribeInfoAttribute GetEnumDescribe<T>(string enumValue) where T : struct
		{
			if (enumValue == null)
			{
				throw new ArgumentNullException("enumValue");
			}
			Type typeFromHandle = typeof(T);
			if (!typeFromHandle.IsEnum)
			{
				throw new Exception("目标类型不是Enum");
			}
			IEnumerable<string> enumerable = enumValue.Split(',')?.Where((string x) => !string.IsNullOrWhiteSpace(x))?.Select((string x) => x.Trim());
			if (enumerable == null)
			{
				return null;
			}
			string text = "";
			string text2 = "";
			foreach (string item in enumerable)
			{
				if (!Enum.TryParse<T>(item, out var _))
				{
					continue;
				}
				FieldInfo field = typeFromHandle.GetField(item);
				if (!(field == null))
				{
					DescribeInfoAttribute describeInfoAttribute = Attribute.GetCustomAttribute(field, typeof(DescribeInfoAttribute)) as DescribeInfoAttribute;
					if (describeInfoAttribute != null)
					{
						text = text + item + ",";
						text2 = text2 + describeInfoAttribute.Description + ",";
					}
				}
			}
			string name = (text.EndsWith(",") ? text.Substring(0, text.Length - 1) : text);
			string describe = (text2.EndsWith(",") ? text2.Substring(0, text2.Length - 1) : text2);
			return new DescribeInfoAttribute(describe)
			{
				Name = name
			};
		}

		public static DescribeInfoAttribute GetEnumDescribe<T>(Enum enumValue) where T : struct
		{
			if (enumValue == null)
			{
				return null;
			}
			Type typeFromHandle = typeof(T);
			if (!typeFromHandle.IsEnum)
			{
				throw new Exception("目标类型不是Enum");
			}
			return BuildAttribute.GetEnumDescribe<T>(enumValue.ToString());
		}

		public static string GetEnumDescribeStr<T>(Enum enumValue) where T : struct
		{
			return BuildAttribute.GetEnumDescribe<T>(enumValue)?.Description;
		}

		public static List<T> GetCustomAbList<T>(object entity) where T : Attribute
		{
			if (entity == null)
			{
				throw new ArgumentNullException("entity");
			}
			Type type = entity.GetType();
			PropertyInfo[] properties = type.GetProperties();
			List<T> list = new List<T>();
			PropertyInfo[] array = properties;
			foreach (PropertyInfo element in array)
			{
				T val = Attribute.GetCustomAttribute(element, typeof(T)) as T;
				if (val != null)
				{
					list.Add(val);
				}
			}
			return list;
		}

		public static List<ComDataAttribute> GetComCustomAbList(object entity)
		{
			if (entity == null)
			{
				throw new ArgumentNullException("entity");
			}
			Type type = entity.GetType();
			PropertyInfo[] properties = type.GetProperties();
			List<ComDataAttribute> list = new List<ComDataAttribute>();
			PropertyInfo[] array = properties;
			foreach (PropertyInfo propertyInfo in array)
			{
				ComDataAttribute comDataAttribute = Attribute.GetCustomAttribute(propertyInfo, typeof(ComDataAttribute)) as ComDataAttribute;
				if (comDataAttribute != null)
				{
					comDataAttribute.ByteCount = (ushort)((int)(ushort)comDataAttribute.DataType / 10);
					comDataAttribute.VarName = propertyInfo.Name;
					list.Add(comDataAttribute);
				}
			}
			return list;
		}

		public static void RunSystemIniMethod<T>(T classObj) where T : class, new()
		{
			if (classObj == null)
			{
				throw new ArgumentNullException("classObj");
			}
			Type type = classObj.GetType();
			MethodInfo[] methods = type.GetMethods();
			foreach (MethodInfo each in methods)
			{
				SystemIniAttribute systemIniAttribute = Attribute.GetCustomAttribute(each, typeof(SystemIniAttribute)) as SystemIniAttribute;
				if (systemIniAttribute == null)
				{
					continue;
				}
				try
				{
					if (!systemIniAttribute.IsAsync)
					{
						each.Invoke(classObj, null);
						continue;
					}
					Task.Run(delegate
					{
						each.Invoke(classObj, null);
					});
				}
				catch (Exception innerException)
				{
					throw new Exception(type.Name + " Failed！", innerException);
				}
			}
		}

		public static T RunSystemIniMethod<T>() where T : class, new()
		{
			T val = new T();
			BuildAttribute.RunSystemIniMethod(val);
			return val;
		}

		public static T RunSystemIniMethod<T>(Action<T> act) where T : class, new()
		{
			T val = new T();
			act?.Invoke(val);
			BuildAttribute.RunSystemIniMethod(val);
			return val;
		}

		public static T GetCustomClassAb<T, TClass>() where T : Attribute where TClass : class
		{
			return Attribute.GetCustomAttribute(typeof(TClass), typeof(T)) as T;
		}

		public static string GetComAdr<T, TAb>(Expression<Func<T, object>> exp) where T : class where TAb : ComDataAttribute
		{
			string columnName = LambdaResolver.GetColumnName(exp);
			return BuildAttribute.GetCustomAb<T, TAb>(columnName)?.Adr;
		}

		public static string GetComAdr<T>(Expression<Func<T, object>> exp) where T : class
		{
			string columnName = LambdaResolver.GetColumnName(exp);
			return BuildAttribute.GetCustomAb<T, ComDataAttribute>(columnName)?.Adr;
		}

		public static TAb GetComAb<T, TAb>(Expression<Func<T, object>> exp) where T : class where TAb : ComDataAttribute
		{
			string columnName = LambdaResolver.GetColumnName(exp);
			return BuildAttribute.GetCustomAb<T, TAb>(columnName);
		}

		public static Tuple<bool, string> IsNullDisable<T>(T entity, List<string> list) where T : class, new()
		{
			PropertyInfo[] properties = typeof(T).GetProperties();
			StringBuilder stringBuilder = new StringBuilder();
			bool item = false;
			PropertyInfo[] array = properties;
			foreach (PropertyInfo propertyInfo in array)
			{
				DescribeInfoAttribute describeInfoAttribute = Attribute.GetCustomAttribute(propertyInfo, typeof(DescribeInfoAttribute)) as DescribeInfoAttribute;
				if (describeInfoAttribute != null)
				{
					string value = propertyInfo.GetValue(entity, null)?.ToString().Trim();
					List<string> list2 = new List<string>();
					if (describeInfoAttribute.NullDisableValue.Contains('|'))
					{
						list2 = describeInfoAttribute.NullDisableValue.Split('|').ToList();
					}
					else if (describeInfoAttribute.NullDisableValue.Length > 0)
					{
						list2.Add(describeInfoAttribute.NullDisableValue);
					}
					if (list.Any((string x) => x == value) || list2.Any((string x) => x == value))
					{
						item = true;
						StringBuilder stringBuilder2 = stringBuilder;
						StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(7, 3, stringBuilder2);
						handler.AppendFormatted(describeInfoAttribute.Description);
						handler.AppendLiteral("值不被允许设定");
						handler.AppendFormatted(value);
						handler.AppendFormatted(Environment.NewLine);
						stringBuilder2.Append(ref handler);
					}
				}
			}
			return new Tuple<bool, string>(item, stringBuilder.ToString());
		}
	}
}
